package donajurema.model;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class EstimateList
{
	private ProductList history;
	private Date stockDate;

	
	public EstimateList(ProductList history, Date stockDate)
	{
		this.history = history;
		this.stockDate = stockDate;
	}

	public ArrayList<Product> getEstimate()
	{
	
		List<String> uniqueNames = getUniqueProductNameList(history);
		ArrayList<Product> result = new ArrayList<Product>();
		
		for (String uniqueName : uniqueNames) 
		{
			ArrayList<Product> found = this.history.getAllProductsByName(uniqueName);
			Product newProduct = calculateEstimate(found);
			if (newProduct != null ) {result.add(newProduct);}
		}
		return result;
	}

	private Product calculateEstimate(ArrayList<Product> productList)
	{
		// Only process if we have at least two recorded
		if (productList.size() < 2)  { return null;}

		// Initialize products
		Product newProduct = new Product(productList.get(0).getName(), productList.get(0).getUnit());
	
		//Get the last purchase made.
		Product lastProduct = productList.get(productList.size()-1);
		System.out.println("Name: " + productList.get(0).getName());
		
		// Calculate date difference between first purchase and last one.
		Date firstDate = productList.get(0).getDate();
		Date lastDate = lastProduct.getDate();
		long firstToLastDeltaDays = getDateDiff(firstDate, lastDate);
	    System.out.println("firstToLastDeltaDays: " + firstToLastDeltaDays);
		if (firstToLastDeltaDays < 2) { return null; } 
		
		// Calculate date difference between last buy and now.
		Date nowDate = new Date();
		long lastToNowDeltaDays = getDateDiff(lastDate, nowDate);
		System.out.println("lastToNowDeltaDas: " + lastToNowDeltaDays);
		//if (lastToNowDeltaDays < 1) { return null; }
		
		// Calculate date difference between now and selected stock
		long nowToStockDeltaDays = getDateDiff(nowDate, this.stockDate);
		System.out.println("nowToStockDeltaDays: " + nowToStockDeltaDays);
		
		// Calculate total amount of product that has been purchase excluding the last purchase
		float totalQuantityPurchased = 0;
		productList.remove(lastProduct); //Remove lastProduct from list
		for (Product p : productList)
		{
			totalQuantityPurchased += p.getQuantity();
		}
		System.out.println("totalQuantityPurchased: " + totalQuantityPurchased);
		
		// Calculate daily average use
		float dailyUseAverageQuantity = totalQuantityPurchased / firstToLastDeltaDays;
		System.out.println("dailyUseAverageQuantity: " + dailyUseAverageQuantity);
		
		// Estimate quantity of product still remaining.
		float remainingQuantity = lastProduct.getQuantity() - (lastToNowDeltaDays * dailyUseAverageQuantity);
		System.out.println("remainingQuantity: " + remainingQuantity);

		// Calculate amount we need to purchase
		float purchaseQuantity = (nowToStockDeltaDays * dailyUseAverageQuantity) - remainingQuantity;
		System.out.println("purchaseQuantity: " + purchaseQuantity);
		
		// If you have to buy less than 1, probably should not buy it!
		if (purchaseQuantity < 1) { return null; } 
		
		int quantity = (int)Math.ceil(purchaseQuantity);
		System.out.println("int quantity: " + quantity);

		newProduct.setQuantity(quantity);

		return newProduct;
	}
	
	private List<String> getUniqueProductNameList(ProductList list)
	{
		ArrayList<Product> products = list.getProducts();
		Set<String> uniqueNameSet = new HashSet<String>();
		for (Product p : products)
    	{
			uniqueNameSet.add(p.getName());
    	}
		return new ArrayList<String>(uniqueNameSet);
	}
	
	private long getDateDiff(Date start, Date end)
	{
        Calendar ca1 = Calendar.getInstance();
        Calendar ca2 = Calendar.getInstance();

        // Set the date for both of the calendar to get difference
        ca1.setTime(start);
        ca2.setTime(end); 

        // Get date in milliseconds
        double milisecond1 = ca1.getTimeInMillis();
        //System.out.println(milisecond1);
        double milisecond2 = ca2.getTimeInMillis();
        //System.out.println(milisecond2);

        // Find date difference in milliseconds
        double diffInMSec = milisecond2 - milisecond1;
        //System.out.println("diffInMSec " + diffInMSec);

        // Find date difference in days 
        // (24 hours 60 minutes 60 seconds 1000 millisecond)
        double diffOfDays = diffInMSec / (24 * 60 * 60 * 1000);
        //System.out.println("diffOfDays " + diffOfDays);
        
        long result = (long)Math.round(diffOfDays);
        
        return result;
	}
}
